Binary match date strings#39
Conversation
matthewlehner
left a comment
There was a problem hiding this comment.
This looks great! I just wanted to highlight some of the stuff I found here when looking at this yesterday.
Hopefully this is helpful!
Co-authored-by: Matthew Lehner <matthew@mpl.io>
| # get UTC, then express in the post-gap offset (EDT) → 3:30 AM EDT. | ||
| case DateTime.new(date, time, timezone) do | ||
| {:ok, dt} -> dt | ||
| {:ambiguous, first, _second} -> first |
There was a problem hiding this comment.
Ah right, this is correct per the spec!
If, based on the definition of the referenced time zone, the local
time described occurs more than once (when changing from daylight
to standard time), the DATE-TIME value refers to the first
occurrence of the referenced time.
| case DateTime.new(date, time, timezone) do | ||
| {:ok, dt} -> dt | ||
| {:ambiguous, first, _second} -> first | ||
| {:gap, _just_before, just_after} -> just_after |
There was a problem hiding this comment.
Ah, if only this could be simple!
The gap requires a calculating when the occurrence would be based on UTC, then putting it into the timezone after.
Something like this:
| {:gap, _just_before, just_after} -> just_after | |
| {:gap, just_before, _just_after} -> | |
| pre_gap_offset = just_before.utc_offset + just_before.std_offset | |
| naive = NaiveDateTime.new!(date, time) | |
| utc = NaiveDateTime.add(naive, -pre_gap_offset, :second) | |
| DateTime.shift_zone!(DateTime.from_naive!(utc, "Etc/UTC"), timezone) |
The spec says:
2:30 AM in a spring-forward gap → apply pre-gap offset (EST) to
get UTC, then express in the post-gap offset (EDT) → 3:30 AM EDT.
Super glad we're handling this 😂
it might be worth extracting this to a private function or adding a comment here just to make it clear why this is the way it is.
There was a problem hiding this comment.
The gap requires a calculating when the occurrence would be based on UTC
It's even easier: the "gapped" time is somewhere in the gap. So one needs to calculate the offset from where the discontinuity starts (e.g. spring forward at 02:00) to the gapped time, then shift the actual time (after the gap ends) by that amount.
So 02:30 in a gap of 02:00 -> 03:00 becomes 3:00 + (2:30 - 2:00). Resolved in 7fd6f35
gap times return the before/after moments of the gap. our time is somewhere in that gap. so shift the after by the amount the gapped time would have been after the start
2987cc9 to
7fd6f35
Compare
Issue: #32
This replaces uses of
Timex.parse/2inICal.Deserialzewith binary matching.One nice nice side effect: the code longer creates a new string with the timezone just to parse it out again.